package com.atguigu04.threadsafemore.singleton;

import java.sql.SQLOutput;

/**
 * ClassName: SingletonTest
 * Package: com.atguigu04.threadsafemore.singleton
 * Description:
 *
 * @Author BuTang
 * @Create 2023/5/15 15:02
 * @Version 1.0
 */
public class SingletonTest {
    static Singleton s1 = null;//注意此处不要直接 s1= SingletonTest.getInstance，我是猪我这么做了呜呜呜
    static Singleton s2 = null;
    static Singleton s3 = null;

    public static void main(String[] args) {

        Thread t1 = new Thread() {
            @Override
            public void run() {
                s1 = Singleton.getInstance();
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                s2 = Singleton.getInstance();
            }
        };

        Thread t3 = new Thread() {
            @Override
            public void run() {
                s3 = Singleton.getInstance();
            }
        };


        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");
        t1.start();
        t2.start();
        t3.start();

        try {
            t1.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        try {
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        try {
            t3.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

        System.out.println(s1 == s2 );
    }
}

class Singleton {

    private static volatile Singleton instance = null;

    private Singleton() {

    }

    //方式一，把方法声明为synchroized

//    public static synchronized Singleton getInstance() {
//
//        System.out.println(Thread.currentThread().getName()+"线程进入");
//        if (instance == null) {
//
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            instance = new Singleton();
//        }
//        return instance;
//    }


    //方式二，把内部程序声明为synchroized

//    public static  Singleton getInstance() {
//        synchronized(Singleton.class){
//        System.out.println(Thread.currentThread().getName()+"线程进入");
//        if (instance == null) {
//
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            instance = new Singleton();
//        }
//        return instance;
//    }}


    //方式三，volatile避免指令重排
    public static  Singleton getInstance() {
        synchronized(Singleton.class){
        System.out.println(Thread.currentThread().getName()+"线程进入");
        if (instance == null) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            instance = new Singleton();
        }
        return instance;
    }}
}


